package cn.memorynine.consumer.service;

import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
import cn.memorynine.common.enums.ResultEnum;
import cn.memorynine.common.model.ResponseWrapper;
import cn.memorynine.common.tool.ImageCodeTool;
import cn.memorynine.common.tool.JwtService;
import cn.memorynine.consumer.model.TokenModel;
import cn.memorynine.consumer.model.consumer.login.*;
import cn.memorynine.dao.entity.Consumer;
import cn.memorynine.dao.mapper.ConsumerMapper;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class ConsumerLoginService {

    @Autowired
    private JwtService jwtService;

    @Autowired
    private ConsumerMapper consumerMapper;

    /**
     * 登录失败缓存
     */
    static Cache<String, Integer> loginFailCache = CacheUtil.newTimedCache(300000);

    /**
     * 1. 用户登录是否需要图片验证码
     * @return
     */
    public ResponseWrapper needImageCode(NeedImageCodeParam param){
        //1. 准备结果集
        NeedImageCodeResult needImageCodeResult = new NeedImageCodeResult();

        String macAddress = param.getMacCode();
        Integer times = loginFailCache.get(macAddress);

        //如果失败次数小于3次，则不需要验证码
        if (times == null || times < 3){
            //说明此人还未登录失败过,或者还没有失败3次
            needImageCodeResult.setIsNeed(false);
        } else {
            //如果失败已满3次，则返回需要图形验证码
            needImageCodeResult.setIsNeed(true);
        }

        //最后一步，返回结果
        return ResponseWrapper.markSuccess(needImageCodeResult);
    }

    /**
     * 2. 获取图片验证码
     * @return
     */
    public ResponseWrapper imageCode(ImageCodeParam param){
        ImageCodeResult imageCodeResult = new ImageCodeResult();

        Map<String, Object> imageCode = ImageCodeTool.getImageCode();

        imageCodeResult.setId((String) imageCode.get("imageCodeKey"));
        imageCodeResult.setImageData((String) imageCode.get("imageCodeBase64"));

        //最后一步，返回结果
        return ResponseWrapper.markSuccess(imageCodeResult);
    }

    /**
     * 3. 用户登录
     * @return
     */
    public ResponseWrapper login(LoginParam param) throws UnsupportedEncodingException {

        LoginResult loginResult = new LoginResult();

        //1.准备数据
        ResultEnum loginError = ResultEnum.LOGIN_ERROR;
        String macAddress = param.getMacCode();
        boolean isLoginSuccess = true;
        TokenModel tokenModel = new TokenModel();

        //2.如果缓冲池中无该mac地址，则加入，并置值为0
        if(loginFailCache.get(macAddress) == null){
            loginFailCache.put(macAddress,0);
        }

        //3.如果失败超过3次，则必须进行验证码校验，否则不需要
        if (loginFailCache.get(macAddress) >= 3){
            //3.1 需要检验验证码，验证码正确才进行账户密码确认
            if (ImageCodeTool.imageCodeCheck(param.getImageId(),param.getImageCode())){
                //验证码正确，进行账户确认
                //查询数据库中是否有这个用户
                List<Consumer> staffList = consumerMapper.selectList(new LambdaQueryWrapper<Consumer>()
                        .and(i->i.eq(Consumer::getPhone, param.getUserName())
                                .or()
                                .eq(Consumer::getEmail, param.getUserName()))
                        .eq(Consumer::getLoginKey, param.getLoginKey()));

                if (!staffList.isEmpty()){
                    //如果有则登录成功，并返回一个token
                    tokenModel.setTokenConsumerAid(staffList.get(0).getAid());
                    String str = JSONObject.toJSONString(tokenModel);
                    String token = jwtService.createToken(str);

                    loginResult.setIsNeedImageCode(false);
                    loginResult.setStatusId(staffList.get(0).getStatusId());
                    loginResult.setName(staffList.get(0).getName());
                    loginResult.setToken(token);
                } else {
                    //登录失败了
                    isLoginSuccess = false;
                    loginError = ResultEnum.LOGIN_ERROR;
                }
            }
            //3.2 验证码错误
            else {
                isLoginSuccess = false;
                loginError = ResultEnum.CAPTCHA_CHECK_ERROR;
            }
        } else {
            //不需要验证验证码
            //查询数据库中是否有这个用户
            List<Consumer> staffList = consumerMapper.selectList(
                    Wrappers.<Consumer>lambdaQuery()
                            .and(i->i.eq(Consumer::getPhone, param.getUserName())
                                    .or()
                                    .eq(Consumer::getEmail, param.getUserName()))
                            .eq(Consumer::getLoginKey, param.getLoginKey()));
            if (!staffList.isEmpty()){
                //如果有则登录成功，并返回一个token
                tokenModel.setTokenConsumerAid(staffList.get(0).getAid());
                String tokenString = JSONObject.toJSONString(tokenModel);
                String token = jwtService.createToken(tokenString);

                loginResult.setIsNeedImageCode(false);
                loginResult.setStatusId(staffList.get(0).getStatusId());
                loginResult.setName(staffList.get(0).getName());
                loginResult.setToken(token);
            } else {
                //登录失败
                isLoginSuccess = false;
                loginError = ResultEnum.LOGIN_ERROR;
            }
        }

        //4. 登录失败时：失败次数+1，判断是否需要验证码
        if(!isLoginSuccess){
            //登录失败，则在缓存池中将该mac地址的次数+1
            loginFailCache.put(macAddress,loginFailCache.get(macAddress)+1);
            //判断是否需要验证码
            //ii.查看当前用户mac地址已失败几次
            Integer times = loginFailCache.get(macAddress);

            if (times == null || times < 3){
                //说明此人还未登录失败过,或者还没有失败3次
                loginResult.setIsNeedImageCode(false);
            } else {
                //如果失败已满3次，则返回需要图形验证码
                loginResult.setIsNeedImageCode(true);
            }
            return ResponseWrapper.markError(loginError,loginResult);
        }

        //最后一步，返回结果
        return ResponseWrapper.markSuccess(loginResult);
    }
}
